package lyc.springcloud.admin.utils;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.JwtBuilder;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;

import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import javax.servlet.http.HttpServletRequest;
import java.security.Key;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

@Configuration
public class JwtUtil {
    // @Value("${jwt.secret}")
    // Spring的注解不支持静态的变量和方法,另外写一个set
    private static String jwtSecret;
    private static int TTL_MILLIS = 900000;

    @Value("${jwt.secret}")
    public void setJwtSecret(String jwtSecret) {
        JwtUtil.jwtSecret = jwtSecret;
    }

    /**
     * 获取jwt密钥
     */
    private static SecretKey getJwtSecretVal() {
        byte[] encodeSecret = Base64.decodeBase64(jwtSecret);
        return new SecretKeySpec(encodeSecret, "AES");
    }

    /**
     * 生成JWT
     */
    private static String createJWT(Map<String, Object> tokenSubject, Integer ttlMillis) {
        long nowMillis = System.currentTimeMillis();
        Date now = new Date(nowMillis);
        SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;
        //生成签名密钥
        Key signingKey = getJwtSecretVal();

        //添加构成JWT的参数
        JwtBuilder builder = Jwts.builder()
                .setHeaderParam("alg", "HS256")
                .setIssuedAt(now)
                .setClaims(tokenSubject)
                .signWith(signatureAlgorithm, signingKey);
        if (ttlMillis >= 0) {
            long expMillis = nowMillis + ttlMillis;
            Date exp = new Date(expMillis);
            builder.setExpiration(exp);
        }
        //生成JWT
        return builder.compact();
    }

    /**
     * 解析JWT
     */
    private static Claims parseJWT(String jwt) throws Exception {
        SecretKey jwtSecret = getJwtSecretVal();
        return Jwts.parser()
                .setSigningKey(jwtSecret)
                .parseClaimsJws(jwt).getBody();
    }

    /**
     * 生成Token
     */
    public static String createToken(Map<String, Object> params) {
        return createJWT(params, TTL_MILLIS);
    }

    /**
     * 解析Token
     */
    public static Claims parseToken(HttpServletRequest request) throws Exception {
        String token = getToken(request);
        token = token == null ? "" : token;
        return JwtUtil.parseJWT(token);


    }

    /**
     * 获取请求头Header中的Token
     * 头部没有token，就从url中取，特殊url（下载，导出等）token放在url中
     */
    public static String getToken(HttpServletRequest request) {
        String token = request.getHeader("web-token");
        // 前端下载，某些特殊url后拼接token处理
        if(StringUtils.isEmpty(token) && urlHasToken(request)) {
            return request.getParameter("web-token");
        }
        return token;
    }

    /**
     * 获取url中的Token
     */
    private static Boolean urlHasToken(HttpServletRequest request) {
        String requestUrl = request.getRequestURI();
        for (String url : UrlTokenList.URL_TOKEN_LIST) {
            if(StringUtils.containsIgnoreCase(requestUrl, url)) {
                return true;
            }
        }
        return false;
    }
}
